package controller;

import model.Map;
import model.Pacman;
import model.Ghost;
import model.UndoStack;
import model.Leaderboard;
import ds.SkillTree;
import view.GamePanel;
import java.awt.event.*;
import java.util.List;
import javax.swing.Timer;

public class GameController implements ActionListener, KeyListener {
    private GamePanel gamePanel;
    private Timer timer;
    private Map map;
    private Pacman pacman;
    private List<Ghost> ghosts;
    private UndoStack undoStack;
    private Leaderboard leaderboard;
    private SkillTree skillTree;
    private int ghostMoveCounter = 0;
    private int ghostMoveInterval = 3;
    private boolean gameOver = false;
    private int score = 0;

    public GameController(GamePanel gamePanel, Map map, Pacman pacman, List<Ghost> ghosts, UndoStack undoStack, Leaderboard leaderboard, SkillTree skillTree) {
        this.gamePanel = gamePanel;
        this.map = map;
        this.pacman = pacman;
        this.ghosts = ghosts;
        this.undoStack = undoStack;
        this.leaderboard = leaderboard;
        this.skillTree = skillTree;
        this.timer = new Timer(100, this);
        this.timer.start();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (gameOver) return;
        ghostMoveCounter++;
        if (ghostMoveCounter >= ghostMoveInterval) {
            for (int i = 0; i < ghosts.size(); i++) {
                Ghost ghost = ghosts.get(i);
                int targetRow = pacman.getRow();
                int targetCol = pacman.getCol();
                if (i == 1) {
                    int[] front = pacman.getFront(4, map);
                    targetRow = front[0];
                    targetCol = front[1];
                } else if (i == 2) {
                    Ghost red = ghosts.get(0);
                    targetRow = (pacman.getRow() + red.row) / 2;
                    targetCol = (pacman.getCol() + red.col) / 2;
                } else if (i == 3) {
                    int dist = Math.abs(ghost.row - pacman.getRow()) + Math.abs(ghost.col - pacman.getCol());
                    if (dist > 8) {
                        targetRow = pacman.getRow();
                        targetCol = pacman.getCol();
                    } else {
                        targetRow = map.getRows() - 2;
                        targetCol = 1;
                    }
                }
                ghost.moveBFS(map, targetRow, targetCol);
            }
            ghostMoveCounter = 0;
        }
        for (Ghost ghost : ghosts) {
            if (ghost.row == pacman.getRow() && ghost.col == pacman.getCol()) {
                gameOver = true;
                timer.stop();
                gamePanel.showGameOverDialog();
                break;
            }
        }
        gamePanel.repaint();
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (gameOver) return;
        if (e.getKeyCode() == KeyEvent.VK_Z) {
            int[] pos = undoStack.pop();
            if (pos != null) {
                pacman.setPosition(pos[0], pos[1]);
                gamePanel.repaint();
            }
        } else {
            pacman.setDirection(e.getKeyCode());
            undoStack.push(pacman.getRow(), pacman.getCol());
            int oldRow = pacman.getRow();
            int oldCol = pacman.getCol();
            boolean ateDot = pacman.move(map);
            if (ateDot) {
                score += 10;
                gamePanel.playEatSound();
            }
            if (pacman.getRow() != oldRow || pacman.getCol() != oldCol) {
                gamePanel.repaint();
            }
            for (Ghost ghost : ghosts) {
                if (ghost.row == pacman.getRow() && ghost.col == pacman.getCol()) {
                    gameOver = true;
                    timer.stop();
                    gamePanel.showGameOverDialog();
                    break;
                }
            }
            gamePanel.repaint();
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {}
    @Override
    public void keyTyped(KeyEvent e) {}

    public int getScore() { return score; }
    public boolean isGameOver() { return gameOver; }
    public void restartGame() {
        // 这里可调用gamePanel的restartGame逻辑
    }
} 